package com.bakery.service;

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bakery.dto.EmployeeDTO;
import com.bakery.dto.LoginDTO;
import com.bakery.entity.Employee;
import com.bakery.mapper.EmployeeMapper;
import com.bakery.vo.LoginVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 员工Service
 *
 * @author bakery
 */
@Service
public class EmployeeService extends ServiceImpl<EmployeeMapper, Employee> {
    
    /**
     * 员工登录
     */
    public LoginVO login(LoginDTO dto) {
        // 查询员工
        LambdaQueryWrapper<Employee> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Employee::getAccount, dto.getAccount());
        wrapper.eq(Employee::getStatus, 1); // 只能登录在职员工
        Employee employee = getOne(wrapper);
        
        if (employee == null) {
            throw new RuntimeException("账号或密码错误");
        }
        
        // 验证密码
        if (!BCrypt.checkpw(dto.getPassword(), employee.getPassword())) {
            throw new RuntimeException("账号或密码错误");
        }
        
        // 登录成功，生成token
        StpUtil.login(employee.getId());
        String token = StpUtil.getTokenValue();
        
        // 将用户信息存入Session
        StpUtil.getSession().set("employee", employee);
        
        return new LoginVO(token, employee.getId(), employee.getName(), 
                employee.getAccount(), employee.getRole());
    }
    
    /**
     * 获取当前登录员工
     */
    public Employee getCurrentEmployee() {
        if (!StpUtil.isLogin()) {
            throw new RuntimeException("未登录");
        }
        return (Employee) StpUtil.getSession().get("employee");
    }
    
    /**
     * 员工登出
     */
    public void logout() {
        StpUtil.logout();
    }
    
    /**
     * 分页查询员工
     */
    public Page<Employee> getEmployeePage(Integer page, Integer size, String keyword, String role, Integer status) {
        LambdaQueryWrapper<Employee> wrapper = new LambdaQueryWrapper<>();
        
        if (StrUtil.isNotBlank(keyword)) {
            wrapper.and(w -> w.like(Employee::getName, keyword)
                    .or()
                    .like(Employee::getAccount, keyword));
        }
        
        if (StrUtil.isNotBlank(role)) {
            wrapper.eq(Employee::getRole, role);
        }
        
        if (status != null) {
            wrapper.eq(Employee::getStatus, status);
        }
        
        wrapper.orderByDesc(Employee::getCreateTime);
        
        Page<Employee> employeePage = page(new Page<>(page, size), wrapper);
        
        // 隐藏密码
        employeePage.getRecords().forEach(emp -> emp.setPassword(null));
        
        return employeePage;
    }
    
    /**
     * 新增员工
     */
    @Transactional(rollbackFor = Exception.class)
    public void addEmployee(EmployeeDTO dto) {
        // 检查账号是否已存在
        LambdaQueryWrapper<Employee> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Employee::getAccount, dto.getAccount());
        if (count(wrapper) > 0) {
            throw new RuntimeException("账号已存在");
        }
        
        Employee employee = new Employee();
        employee.setName(dto.getName());
        employee.setAccount(dto.getAccount());
        
        // 密码加密
        String password = StrUtil.isBlank(dto.getPassword()) ? "123456" : dto.getPassword();
        employee.setPassword(BCrypt.hashpw(password));
        
        employee.setRole(dto.getRole());
        employee.setPhone(dto.getPhone());
        employee.setHireDate(dto.getHireDate());
        employee.setStatus(dto.getStatus() != null ? dto.getStatus() : 1);
        
        save(employee);
    }
    
    /**
     * 更新员工
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateEmployee(EmployeeDTO dto) {
        Employee employee = getById(dto.getId());
        if (employee == null) {
            throw new RuntimeException("员工不存在");
        }
        
        // 如果修改了账号，检查新账号是否已存在
        if (!employee.getAccount().equals(dto.getAccount())) {
            LambdaQueryWrapper<Employee> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Employee::getAccount, dto.getAccount());
            wrapper.ne(Employee::getId, dto.getId());
            if (count(wrapper) > 0) {
                throw new RuntimeException("账号已存在");
            }
        }
        
        employee.setName(dto.getName());
        employee.setAccount(dto.getAccount());
        
        // 如果提供了新密码，则更新密码
        if (StrUtil.isNotBlank(dto.getPassword())) {
            employee.setPassword(BCrypt.hashpw(dto.getPassword()));
        }
        
        employee.setRole(dto.getRole());
        employee.setPhone(dto.getPhone());
        employee.setHireDate(dto.getHireDate());
        
        if (dto.getStatus() != null) {
            employee.setStatus(dto.getStatus());
        }
        
        updateById(employee);
    }
    
    /**
     * 删除员工
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteEmployee(Long id) {
        Employee currentEmployee = getCurrentEmployee();
        if (!"MANAGER".equals(currentEmployee.getRole())) {
            throw new RuntimeException("只有店长可以删除员工");
        }
        
        if (currentEmployee.getId().equals(id)) {
            throw new RuntimeException("不能删除自己");
        }
        
        removeById(id);
    }
    
    /**
     * 修改密码
     */
    @Transactional(rollbackFor = Exception.class)
    public void changePassword(String oldPassword, String newPassword) {
        Employee employee = getCurrentEmployee();
        
        // 验证旧密码
        if (!BCrypt.checkpw(oldPassword, employee.getPassword())) {
            throw new RuntimeException("旧密码错误");
        }
        
        // 更新密码
        employee.setPassword(BCrypt.hashpw(newPassword));
        updateById(employee);
        
        // 更新Session中的员工信息
        StpUtil.getSession().set("employee", employee);
    }
}

